package com.tanhua.server.service;

import com.tanhua.commons.template.OssTemplate;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.db.UserStatus;
import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.Visitor;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.PublishVO;
import com.tanhua.domain.vo.VisitorVO;
import com.tanhua.dubbo.api.*;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.RelativeDateFormat;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class MovementsService {
    @Reference
    private VisitorApi visitorApi;
    @Reference
    private PublishApi publishApi;
    @Reference
    private CommentApi commentApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private MovementsMQService mqService;
    @Reference
    private UserStatusApi userStatusApi;

    public ResponseEntity recommend(int page, int pagesize) {
        //获取当前用户的id
        Long userId = UserHolder.getUserId();
        //查询给当前用户推荐的动态
        PageResult<Publish> pageResult = findRecommendFromRedis(page, pagesize);
        if (pageResult == null) {
             pageResult = publishApi.findByRecommend(userId, page, pagesize);
        }
        //把动态信息转换成PublishVO
        List<PublishVO> voList = getPublishVo(pageResult, userId);

        // 转换成PublishVO的分页对象
        PageResult<PublishVO> vo = new PageResult<>();
        BeanUtils.copyProperties(pageResult, vo);
        vo.setItems(voList);

        return ResponseEntity.ok(vo);
    }

    private PageResult<Publish> findRecommendFromRedis(int page, int pagesize) {
        //从Redis中查询推荐的动态：100092,100092,18,20,1,20,22,4,100092,23
        String publishVidStr = redisTemplate.opsForValue().get("QUANZI_PUBLISH_RECOMMEND_" + UserHolder.getUserId());
        if (publishVidStr == null) {
            return null;
        }
        String[] pids = publishVidStr.split(",");

        //推荐的动态总数量
        int count = pids.length;
        //计算分了多少页
        int pages = (int) Math.ceil(count * 1.0 / pagesize);
        //如果页码大于总页数直接返回
        if (page > pages) {
            return null;
        }
        //计算查询的索引范围
        int start = (page - 1) * pagesize;
        int end = start + pagesize;
        if (end > count) {
            end = count;
        }
        //查询每个pid对应的publish
        List<Long> pidList = new ArrayList<>();
        for (int i = start; i < end; i++) {
            pidList.add(Long.parseLong(pids[i]));
        }
        List<Publish> publishList = publishApi.findByPids(pidList);

        return new PageResult<>(count, pagesize, pages, page, publishList);
    }

    public ResponseEntity movements(Publish publish, MultipartFile[] imageContent) throws IOException {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        UserInfo userInfo = userInfoApi.findById(userId);
        //校验用户是否冻结

        if (userInfo.getUserStatus().equals("2")) {
            UserStatus userStatus = userStatusApi.findByUserId(userId.intValue());
            Integer freezingRange = userStatus.getFreezingRange();
            if (freezingRange == 3) {
                return ResponseEntity.status(503).body("账户发布动态功能已封禁,");
            }
        }
        //把图片上传到阿里云
        List<String> imageList = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String path = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            imageList.add(path);
        }
        //把图片存储到publish中
        publish.setMedias(imageList);
        publish.setUserId(userId);
        publish.setSeeType(1);
        //待审核
        publish.setState(0);
        //保存动态
        String publishId = publishApi.save(publish);
        //发送消息
        rocketMQTemplate.convertAndSend("tanhua-publish", publishId);
        //大数据推荐
        mqService.savePublishMessage(publishId);
        return ResponseEntity.ok(null);
    }

    public ResponseEntity friendPublishList(int page, int pagesize) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //获取当前用户的好友动态列表
        PageResult<Publish> pageResult = publishApi.findByTimeline(page, pagesize, userId);
        //转换成PublishVO
        List<PublishVO> voList = getPublishVo(pageResult, userId);
        // 转换成PublishVO的分页对象
        PageResult<PublishVO> vo = new PageResult<>();
        BeanUtils.copyProperties(pageResult, vo);
        vo.setItems(voList);
        return ResponseEntity.ok(vo);

    }

    public ResponseEntity all(int page, int pagesize, Long userId) {
        if (userId == null) {
            userId = UserHolder.getUserId();
        }
        //查询userId对应的相册
        PageResult<Publish> pageResult = publishApi.findAlbumList(page, pagesize, userId);
        log.info("====" + pageResult);
        //把每个Publish转换成PublishVO
        List<PublishVO> voList = getPublishVo(pageResult, userId);
        //构造返回值
        PageResult<PublishVO> voPageResult = new PageResult<>();
        BeanUtils.copyProperties(pageResult, voPageResult);
        voPageResult.setItems(voList);

        return ResponseEntity.ok(voPageResult);
    }

    public ResponseEntity like(String publishId) {
        //获取当前用户的id
        Long userId = UserHolder.getUserId();
        //补全数据
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setUserId(userId);
        //   评论类型：1点赞，2评论，3喜欢
        comment.setCommentType(1);
        //   评论内容：1对动态评论，2对视频评论，3对评论评论
        comment.setPubType(1);
        Publish publish = publishApi.findById(publishId);
        comment.setPublishUserId(publish.getUserId());
        //保存评论，得到点赞数
        long count = commentApi.save(comment);
        //当前用户点赞，记录到redis中
        redisTemplate.opsForValue().set("publish_like_" + userId + "_" + publishId, "1");

        //大数据发送消息
        mqService.likePublishMessage(publishId);
        return ResponseEntity.ok(count);
    }

    public ResponseEntity dislike(String publishId) {
        //获取当前用户的id
        Long userId = UserHolder.getUserId();
        //补全数据
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setUserId(userId);
        //   评论类型：1点赞，2评论，3喜欢
        comment.setCommentType(1);
        //删除评论
        long count = commentApi.remove(comment);
        //当前用户取消点赞，从redis中删除记录
        redisTemplate.delete("publish_like_" + userId + "_" + publishId);
        //大数据发送消息
        mqService.unlovePublishMessage(publishId);
        return ResponseEntity.ok(count);
    }

    public ResponseEntity love(String publishId) {
        //获取当前用户的id
        Long userId = UserHolder.getUserId();
        //补全数据
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setUserId(userId);
        //   评论类型：1点赞，2评论，3喜欢
        comment.setCommentType(3);
        //   评论内容：1对动态评论，2对视频评论，3对评论评论
        comment.setPubType(1);
        Publish publish = publishApi.findById(publishId);
        comment.setPublishUserId(publish.getUserId());
        //保存评论，得到点赞数
        long count = commentApi.save(comment);
        //当前用户点赞，记录到redis中
        redisTemplate.opsForValue().set("publish_love_" + userId + "_" + publishId, "1");

        //大数据发送消息
        mqService.lovePublishMessage(publishId);
        return ResponseEntity.ok(count);
    }

    public ResponseEntity unlove(String publishId) {
        //获取当前用户的id
        Long userId = UserHolder.getUserId();
        //补全数据
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(publishId));
        comment.setUserId(userId);
        //   评论类型：1点赞，2评论，3喜欢
        comment.setCommentType(3);
        //删除评论
        long count = commentApi.remove(comment);
        //当前用户取消点赞，从redis中删除记录
        redisTemplate.delete("publish_love_" + userId + "_" + publishId);

        //大数据发送消息
        mqService.unlovePublishMessage(publishId);
        return ResponseEntity.ok(count);
    }

    private List<PublishVO> getPublishVo(PageResult<Publish> pageResult, Long userId) {
        //转换成PublishVO
        List<PublishVO> voList = new ArrayList<>();
        for (Publish publish : pageResult.getItems()) {
            PublishVO vo = new PublishVO();
            vo.setId(publish.getId().toHexString());

            //发表人的详细信息
            UserInfo userInfo = userInfoApi.findById(publish.getUserId());
            BeanUtils.copyProperties(userInfo, vo);
            if (userInfo.getTags() != null) {
                vo.setTags(userInfo.getTags().split(","));
            }

            //动态信息
            BeanUtils.copyProperties(publish, vo);
            vo.setId(publish.getId().toHexString());
            vo.setImageContent(publish.getMedias().toArray(new String[]{}));
            vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
            vo.setDistance("0.05km");

            Boolean like = redisTemplate.hasKey("publish_like_" + userId + "_" + publish.getId().toHexString());
            vo.setHasLiked(like ? 1 : 0);
            Boolean love = redisTemplate.hasKey("publish_love_" + userId + "_" + publish.getId().toHexString());
            vo.setHasLoved(love ? 1 : 0);

            voList.add(vo);
        }
        return voList;
    }

    public ResponseEntity findOnePublish(String publishId) {
        //查询publishId对应的动态
        Publish publish = publishApi.findOnePublish(publishId);
        //把结果转换成vo
        PublishVO vo = new PublishVO();
        //把发布人信息封装到vo中
        UserInfo userInfo = userInfoApi.findById(publish.getUserId());
        BeanUtils.copyProperties(userInfo, vo);
        if (userInfo.getTags() != null) {
            vo.setTags(userInfo.getTags().split(","));
        }
        //把动态信息封装到vo中
        BeanUtils.copyProperties(publish, vo);
        vo.setId(publish.getId().toHexString());
        vo.setImageContent(publish.getMedias().toArray(new String[]{}));
        vo.setDistance("0.05km");
        vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
        //当前用户是否点赞，是否喜欢
        Boolean like = redisTemplate.hasKey("publish_like_" + publish.getUserId() + "_" + publish.getId().toHexString());
        vo.setHasLiked(like ? 1 : 0);
        Boolean love = redisTemplate.hasKey("publish_love_" + publish.getUserId() + "_" + publish.getId().toHexString());
        vo.setHasLoved(love ? 1 : 0);

        return ResponseEntity.ok(vo);
    }

    public ResponseEntity findVisitorList() {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //查找来访记录，先从redis中查找上次查看记录时间
        String time = redisTemplate.opsForValue().get("visitor_time_" + userId);
        List<Visitor> visitorList = null;
        if (time == null) {
            //没有查看过来访记录，从Mongodb中查询最近5条
            visitorList = visitorApi.findVisitorListByCount(userId, 5);
        } else {
            //之前有过查看记录，只需要查询访问后的来访记录
            visitorList = visitorApi.findVisitorListByStartDate(userId, Long.valueOf(time));
        }
        //把本次记录时间，存储到redis中
        redisTemplate.opsForValue().set("visitor_time_" + userId, String.valueOf(System.currentTimeMillis()));

        //转换成vo对象
        List<VisitorVO> voList = new ArrayList<>();
        for (Visitor visitor : visitorList) {
            VisitorVO vo = new VisitorVO();
            UserInfo userInfo = userInfoApi.findById(visitor.getVisitorUserId());
            BeanUtils.copyProperties(userInfo, vo);
            voList.add(vo);
        }
        return ResponseEntity.ok(voList);
    }
}
